////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
//  Copyright (c) Microsoft Corporation. All rights reserved.
//  Implementation for the Discovery4 board (STM32F4): Copyright (c) Oberon microsystems, Inc.
//
//  *** Discovery4 Board Specific IO Port Initialization ***
//  Modified for a custom FPGAkit by Jan Matyas, info at janmatyas.net, 2013 
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <tinyhal.h>
#include "..\..\..\..\DeviceCode\Targets\Native\STM32F4\DeviceCode\stm32f4xx.h"

// ---------------------------------------------------------------------------

// FSMC pin definitions

#define GPIO_PORT_A  (0 * 16)
#define GPIO_PORT_B  (1 * 16)
#define GPIO_PORT_C  (2 * 16)
#define GPIO_PORT_D  (3 * 16)
#define GPIO_PORT_E  (4 * 16)
#define GPIO_PORT_F  (5 * 16)
#define GPIO_PORT_G  (6 * 16)
#define GPIO_PORT_H  (7 * 16)

#define FSMC_NADV_PORT 		GPIO_PORT_B

#define FSMC_DA0_PORT 		GPIO_PORT_D
#define FSMC_DA1_PORT 		GPIO_PORT_D
#define FSMC_DA2_PORT 		GPIO_PORT_D
#define FSMC_DA3_PORT 		GPIO_PORT_D
#define FSMC_DA4_PORT 		GPIO_PORT_E
#define FSMC_DA5_PORT 		GPIO_PORT_E
#define FSMC_DA6_PORT 		GPIO_PORT_E
#define FSMC_DA7_PORT 		GPIO_PORT_E
#define FSMC_DA8_PORT 		GPIO_PORT_E
#define FSMC_DA9_PORT 		GPIO_PORT_E
#define FSMC_DA10_PORT 		GPIO_PORT_E
#define FSMC_DA11_PORT 		GPIO_PORT_E
#define FSMC_DA12_PORT 		GPIO_PORT_E
#define FSMC_DA13_PORT 		GPIO_PORT_D
#define FSMC_DA14_PORT 		GPIO_PORT_D
#define FSMC_DA15_PORT 		GPIO_PORT_D

#define FSMC_NOE_PORT       GPIO_PORT_D
#define FSMC_NWE_PORT       GPIO_PORT_D
#define FSMC_NWAIT_PORT			GPIO_PORT_D
#define FSMC_NE1_PORT       GPIO_PORT_D

#define FSMC_NBL0_PORT      GPIO_PORT_E
#define FSMC_NBL1_PORT      GPIO_PORT_E

#define FSMC_NADV_PIN 		7

#define FSMC_DA0_PIN 			14
#define FSMC_DA1_PIN 			15
#define FSMC_DA2_PIN 			0
#define FSMC_DA3_PIN 			1
#define FSMC_DA4_PIN 			7
#define FSMC_DA5_PIN 			8
#define FSMC_DA6_PIN 			9
#define FSMC_DA7_PIN 			10
#define FSMC_DA8_PIN 			11
#define FSMC_DA9_PIN 			12
#define FSMC_DA10_PIN 		13
#define FSMC_DA11_PIN 		14
#define FSMC_DA12_PIN 		15
#define FSMC_DA13_PIN 		8
#define FSMC_DA14_PIN 		9
#define FSMC_DA15_PIN 		10

#define FSMC_NOE_PIN      4
#define FSMC_NWE_PIN      5
#define FSMC_NWAIT_PIN		6
#define FSMC_NE1_PIN      7

#define FSMC_NBL0_PIN     0
#define FSMC_NBL1_PIN     1

// ------------------------------------------------------------------------
             
/**
 * Enable pin PA8 and set it as a AF0 == MCO1 output (main clock out)
 */ 
void __section(SectionForBootstrapOperations) Enable_MCO1_Pin() {

    const int MCO1_PIN_PA8 = 0 * 16 + 8;
    
    // ensure that the pin mode of PA8 cannot be redefined by the CLR/user application
    CPU_GPIO_ReservePin( MCO1_PIN_PA8, TRUE );
    
    // alt. mode 0x202 
    //  ...  alternate function push-pull  = 2 (0x  2) |
    //  ...  alternate function AF0        = 0 (0x 00) |
    //  ...  pin speed 50 MHz              = 2 (0x200)  
		CPU_GPIO_DisablePin( MCO1_PIN_PA8, RESISTOR_DISABLED, 1, (GPIO_ALT_MODE)0x202 );
}

// ------------------------------------------------------------------------

/**
 * Enable FSMC and configure its respective pins to the proper alternate function
 */ 
void __section(SectionForBootstrapOperations) Enable_FSMC_on_FPGAkit() {

		// enable clock to the FSMC peripheral
		RCC->AHB3ENR |= RCC_AHB3ENR_FSMCEN;
		
		// set up the FSMC parameters 
		// FSMC_BCR1
  	FSMC_Bank1->BTCR[0] =
  			              FSMC_BCR1_ASYNCWAIT  // allow asynchronous wait
  			            | FSMC_BCR1_WAITCFG    // wait active during the wait state
  			            | FSMC_BCR1_WREN       // enable write operations
  			            | (((uint32_t)1) << 7) // reserved bit, must be set to 1
  			            | FSMC_BCR1_FACCEN     // enable access
  			            | FSMC_BCR1_MWID_0     // 16-bit data width
  			            | FSMC_BCR1_MTYP_1     // NOR Flash memory type
  			            | FSMC_BCR1_MUXEN      // enable multiplexed mode
  			            | FSMC_BCR1_MBKEN      // enable the memory bank 1
  			            ;
  	// FSMC_BTR1
  	FSMC_Bank1->BTCR[1] = 
		            FSMC_BTR1_BUSTURN      // bus turn-around = 15 HCLK cycles
  						| FSMC_BTR1_DATAST_3     // data strobe     = 10 HCLK cycles
  						| FSMC_BTR1_DATAST_1
  						| FSMC_BTR1_ADDHLD_1     // address hold    =  3 HCLK cycles
  						| FSMC_BTR1_ADDHLD_0
  						| FSMC_BTR1_ADDSET_3     // address set     =  8 HCLK cycles
  						;		
		
		// configure FSMC pins
		
		// GPIO_ALT_MODE 0x3c2
		// 0x300 == 100 MHz pin speed
		// 0x0c0 == alternate function 0xc == AF 12 
		// 0x002 == alternate function push-pull output
		
		//UINT32 altMode = 0x3c2;
		
		CPU_GPIO_DisablePin(  FSMC_NADV_PORT 	+  FSMC_NADV_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
	
		CPU_GPIO_DisablePin(  FSMC_DA0_PORT 	+  FSMC_DA0_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA1_PORT 	+  FSMC_DA1_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA2_PORT 	+  FSMC_DA2_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA3_PORT 	+  FSMC_DA3_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA4_PORT 	+  FSMC_DA4_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA5_PORT 	+  FSMC_DA5_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA6_PORT 	+  FSMC_DA6_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA7_PORT 	+  FSMC_DA7_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA8_PORT 	+  FSMC_DA8_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA9_PORT 	+  FSMC_DA9_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA10_PORT 	+  FSMC_DA10_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA11_PORT 	+  FSMC_DA11_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA12_PORT 	+  FSMC_DA12_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA13_PORT 	+  FSMC_DA13_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA14_PORT 	+  FSMC_DA14_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_DA15_PORT 	+  FSMC_DA15_PIN 	,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
	
		CPU_GPIO_DisablePin(  FSMC_NOE_PORT   +  FSMC_NOE_PIN     ,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_NWE_PORT   +  FSMC_NWE_PIN     ,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_NWAIT_PORT	+  FSMC_NWAIT_PIN	  ,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
	
		CPU_GPIO_DisablePin(  FSMC_NBL0_PORT  +  FSMC_NBL0_PIN    ,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
		CPU_GPIO_DisablePin(  FSMC_NBL1_PORT  +  FSMC_NBL1_PIN    ,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
					
		// set chip enable pin
		CPU_GPIO_DisablePin(  FSMC_NE1_PORT   +  FSMC_NE1_PIN     ,  RESISTOR_DISABLED, 0, (GPIO_ALT_MODE)0xc2  );
	
		// reserve the FSMC pins so that they cannot be used and redefined in the managed code	
		CPU_GPIO_ReservePin(  FSMC_NADV_PORT 	+  FSMC_NADV_PIN 	,  TRUE );
	
		CPU_GPIO_ReservePin(  FSMC_DA0_PORT 	+  FSMC_DA0_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA1_PORT 	+  FSMC_DA1_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA2_PORT 	+  FSMC_DA2_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA3_PORT 	+  FSMC_DA3_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA4_PORT 	+  FSMC_DA4_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA5_PORT 	+  FSMC_DA5_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA6_PORT 	+  FSMC_DA6_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA7_PORT 	+  FSMC_DA7_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA8_PORT 	+  FSMC_DA8_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA9_PORT 	+  FSMC_DA9_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA10_PORT 	+  FSMC_DA10_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA11_PORT 	+  FSMC_DA11_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA12_PORT 	+  FSMC_DA12_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA13_PORT 	+  FSMC_DA13_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA14_PORT 	+  FSMC_DA14_PIN 	,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_DA15_PORT 	+  FSMC_DA15_PIN 	,  TRUE );
	
		CPU_GPIO_ReservePin(  FSMC_NOE_PORT   +  FSMC_NOE_PIN     ,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_NWE_PORT   +  FSMC_NWE_PIN     ,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_NWAIT_PORT	+  FSMC_NWAIT_PIN	  ,  TRUE );
	
		CPU_GPIO_ReservePin(  FSMC_NBL0_PORT  +  FSMC_NBL0_PIN    ,  TRUE );
		CPU_GPIO_ReservePin(  FSMC_NBL1_PORT  +  FSMC_NBL1_PIN    ,  TRUE );
	
		CPU_GPIO_ReservePin(  FSMC_NE1_PORT   +  FSMC_NE1_PIN     ,  TRUE );	
	
		
}

// ------------------------------------------------------------------------

/**
 * Pasivate FPGA JTAG pins so that they do not interfere with an attached JTAG probe
 */ 
void __section(SectionForBootstrapOperations) Passivate_JTAG_on_FPGAkit() {

		// disable pins that drive FPGA JTAG interface so that an external
		// adapter can be connected
		
		// GPIO_ALT_MODE_1 == analog
		CPU_GPIO_DisablePin(  GPIO_PORT_E   +  3 ,  RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1 );
		CPU_GPIO_DisablePin(  GPIO_PORT_E   +  4 ,  RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1 );
		CPU_GPIO_DisablePin(  GPIO_PORT_E   +  5 ,  RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1 );
		CPU_GPIO_DisablePin(  GPIO_PORT_E   +  6 ,  RESISTOR_DISABLED, 0, GPIO_ALT_MODE_1 );										

}

// ------------------------------------------------------------------------


/**
 * Board-specific GPIO initialization
 */ 
void __section(SectionForBootstrapOperations) BootstrapCode_GPIO() {

    /* Enable GPIO clocks */  
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN
                  | RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN
                  | RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN | RCC_AHB1ENR_GPIOIEN;
    
    // the macro below is to be defined in platform_selector.h
#ifdef STM32F4_ENABLE_MCO1_HSE
		Enable_MCO1_Pin();	
#endif    

#ifdef FPGAkit_ENABLE_FSMC
		Enable_FSMC_on_FPGAkit();
		
#ifndef PLATFORM_ARM_FPGAkit
#error "FPGAkit_ENABLE_FSMC is meaningful only on the FPGAkit platform"
#endif
#endif

#ifdef PLATFORM_ARM_FPGAkit
		Passivate_JTAG_on_FPGAkit();
#endif

}
